﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO.Ports;
using System.Windows.Threading;
using System.IO;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>

    public partial class MainWindow : Window
    {
        bool logging = false;
        String fileName = "";
        int counter = 0;
        int view = 0;
        int hudblank = 0;
        int satellitecoverage = 0;
        String longitude = "";
        String latitude = "";
        String heading = "";
        String sat = "";
        StreamWriter stream;
        String year = "0000", month = "00", day = "00", hours = "00", minutes = "00", seconds = "00";
        double altMeters;

        public MainWindow()
        {
            InitializeComponent();
            open_serial_port();
        }

        void open_serial_port()
        {
            SerialPort p = new SerialPort("COM1");
            p.BaudRate = 38400;
            p.Parity = Parity.None;
            p.StopBits = StopBits.One;
            p.DataBits = 8;
            p.Handshake = Handshake.None;
            p.ReadBufferSize = 16384; 
            p.NewLine = "\r\n";
            p.DataReceived += new SerialDataReceivedEventHandler(DataReceived);
            try
            {
                p.Open();
            }
            catch (Exception e)
            {
                System.Console.Write(e.Message);
                // Do not recover from this crash; close the program
                Environment.Exit(1);
            }
        }

        void DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPort sp1 = (SerialPort)sender;
            Dispatcher.Invoke(DispatcherPriority.Send, new Action<String>(update_hud), sp1.ReadLine());
            //sp1.ReadExisting(); // FIXED IT, BITCHES!!!!
        }

        void update_hud(String serial_entry)
        {
            //System.Console.WriteLine(serial_entry);
            serial_entry = serial_entry.Trim();
            String[] parsed = serial_entry.Split(' ');
            double degree;

            if (parsed[0].Equals("Accel"))
            {
                //GFORCE
                gforceLabel.Text = parsed[1];
            }
            else if (parsed[0].Equals("Avges"))
            {
                //TEMPERATURE
                gforceLabel.Text = parsed[1];
                tempLabel.Text = parsed[2];
            }
            else if (parsed[0].Equals("GPSTM"))
            {
                //System.Console.WriteLine(serial_entry);
                String[] parseddate = parsed[1].Split('/');
                year = parseddate[0];
                month = parseddate[1];
                day = parseddate[2];
                String[] parsedtime = parsed[2].Split(':');
                hours = parsedtime[0];
                minutes = parsedtime[1];
                seconds = parsedtime[2].Split('.')[0];
                timeLabel.Text = hours + ":" + minutes;
                //System.Console.WriteLine(year + "/" + month + "/" + day + " @ " + hours + ":" + minutes + ":" + seconds);
            }
            else if (parsed[0].Equals("GPSLN"))
            {
                //DATALOGGING
                if (logging && stream != null) { log_Data(stream); }
                //SPEED
                speedLabel.Text = parsed[5];
                //ALTITUDE
                double altFeet = System.Convert.ToDouble(parsed[4]);
                altLabel.Text = System.Convert.ToString(altFeet);
                altMeters = altFeet * 0.3048;
                //DIRECTION
                latitude = parsed[2];
                longitude = parsed[3];
                heading = parsed[7];
                sat = parsed[8];
                degree = System.Convert.ToDouble(parsed[7]);
                if ((degree >= 337.5) || (degree < 22.5))
                {
                    directionLabel.Text = "N";
                }
                else if ((degree >= 22.5) && (degree < 67.5))
                {
                    directionLabel.Text = "NE";
                }
                else if ((degree >= 67.5) && (degree < 112.5))
                {
                    directionLabel.Text = "E";
                }
                else if ((degree >= 112.5) && (degree < 157.5))
                {
                    directionLabel.Text = "SE";
                }
                else if ((degree >= 157.5) && (degree < 202.5))
                {
                    directionLabel.Text = "S";
                }
                else if ((degree >= 202.5) && (degree < 247.5))
                {
                    directionLabel.Text = "SW";
                }
                else if ((degree >= 247.5) && (degree < 292.5))
                {
                    directionLabel.Text = "W";
                }
                else if ((degree >= 292.5) && (degree < 337.5))
                {
                    directionLabel.Text = "NW";
                }
            }
            else if (parsed[0].Equals("FGabs"))
            {
                //BATTERY
                batGauge1.Value = (System.Convert.ToDouble(parsed[1])) / 5000 * 100;
            }
            else if (parsed[0].Equals("Buttn"))
            {
                if (parsed[1].Equals("LogData"))
                {
                    if (logging)
                    {
                        recordLabel.Visibility = System.Windows.Visibility.Hidden;
                        logging = false;
                        close_LogFile(stream);
                        stream = null;
                    }
                    else
                    {
                        fileName = "log_" + year + "-" + month + "-" + day + "_" + hours + minutes + seconds;
                        //System.Console.WriteLine(fileName);
                        recordLabel.Visibility = System.Windows.Visibility.Visible;
                        logging = true;
                        counter = 0;
                        stream = make_NewLogFile();
                    }
                }
                else if (parsed[1].Equals("ChangeMode"))
                {
                    //System.Console.WriteLine("ChangeMode");
                    view++;
                    if (view >= 2) { view = 0; }
                    update_GUI_Visibilities();
                }
                else if (parsed[1].Equals("OnOff"))
                {
                    //System.Console.WriteLine("OnOff");
                    if (hudblank == 1) { hudblank = 0; }
                    else { hudblank = 1; }
                    update_GUI_Visibilities();
                }
            }
            else if (parsed[0].Equals("GPSST"))
            {
                if (!parsed[1].Equals("Doing"))
                {
                    satellitecoverage = 0; ////////////////////////////////////////////////////////////////////
                }
                else if (parsed[1].Equals("Doing"))
                {
                    satellitecoverage = 1;
                }
                update_GUI_Visibilities();
            }
        }

        void update_GUI_Visibilities()
        {
            if ( view == 0 && hudblank == 0 ) //half mode
            {
                topBorder.Visibility = System.Windows.Visibility.Hidden;
                bottomBorder.Visibility = System.Windows.Visibility.Hidden;
                batLabel.Visibility = System.Windows.Visibility.Visible;
                batGauge1.Visibility = System.Windows.Visibility.Visible;
                tempLabel.Visibility = System.Windows.Visibility.Hidden;
                gforceLabel.Visibility = System.Windows.Visibility.Hidden;
                altLabel.Visibility = System.Windows.Visibility.Hidden;
                if (satellitecoverage == 1)
                {
                    timeLabel.Visibility = System.Windows.Visibility.Visible;
                    directionLabel.Visibility = System.Windows.Visibility.Visible;
                    speedLabel.Visibility = System.Windows.Visibility.Visible;
                    errorLabel.Visibility = System.Windows.Visibility.Hidden;
                    mph.Visibility = System.Windows.Visibility.Visible;
                }
                else
                {
                    timeLabel.Visibility = System.Windows.Visibility.Hidden;
                    directionLabel.Visibility = System.Windows.Visibility.Hidden;
                    speedLabel.Visibility = System.Windows.Visibility.Hidden;
                    errorLabel.Visibility = System.Windows.Visibility.Visible;
                    mph.Visibility = System.Windows.Visibility.Hidden;
                }
                G.Visibility = System.Windows.Visibility.Hidden;
                C.Visibility = System.Windows.Visibility.Hidden;
                ft.Visibility = System.Windows.Visibility.Hidden;
            }
            else if ( view == 1 && hudblank == 0 ) //full mode
            {
                topBorder.Visibility = System.Windows.Visibility.Visible;
                bottomBorder.Visibility = System.Windows.Visibility.Visible;
                batLabel.Visibility = System.Windows.Visibility.Visible;
                batGauge1.Visibility = System.Windows.Visibility.Visible;
                tempLabel.Visibility = System.Windows.Visibility.Visible;
                gforceLabel.Visibility = System.Windows.Visibility.Visible;
                if (satellitecoverage == 1)
                {
                    timeLabel.Visibility = System.Windows.Visibility.Visible;
                    directionLabel.Visibility = System.Windows.Visibility.Visible;
                    altLabel.Visibility = System.Windows.Visibility.Visible;
                    speedLabel.Visibility = System.Windows.Visibility.Visible;
                    errorLabel.Visibility = System.Windows.Visibility.Hidden;
                    ft.Visibility = System.Windows.Visibility.Visible;
                    mph.Visibility = System.Windows.Visibility.Visible;
                }
                else
                {
                    timeLabel.Visibility = System.Windows.Visibility.Hidden;
                    directionLabel.Visibility = System.Windows.Visibility.Hidden;
                    altLabel.Visibility = System.Windows.Visibility.Hidden;
                    speedLabel.Visibility = System.Windows.Visibility.Hidden;
                    errorLabel.Visibility = System.Windows.Visibility.Visible;
                    ft.Visibility = System.Windows.Visibility.Hidden;
                    mph.Visibility = System.Windows.Visibility.Hidden;
                }
                G.Visibility = System.Windows.Visibility.Visible;
                C.Visibility = System.Windows.Visibility.Visible;
            }
            else //blank mode
            {
                topBorder.Visibility = System.Windows.Visibility.Hidden;
                bottomBorder.Visibility = System.Windows.Visibility.Hidden;
                timeLabel.Visibility = System.Windows.Visibility.Hidden;
                batLabel.Visibility = System.Windows.Visibility.Hidden;
                batGauge1.Visibility = System.Windows.Visibility.Hidden;
                tempLabel.Visibility = System.Windows.Visibility.Hidden;
                directionLabel.Visibility = System.Windows.Visibility.Hidden;
                gforceLabel.Visibility = System.Windows.Visibility.Hidden;
                altLabel.Visibility = System.Windows.Visibility.Hidden;
                speedLabel.Visibility = System.Windows.Visibility.Hidden;
                G.Visibility = System.Windows.Visibility.Hidden;
                C.Visibility = System.Windows.Visibility.Hidden;
                ft.Visibility = System.Windows.Visibility.Hidden;
                mph.Visibility = System.Windows.Visibility.Hidden;
                errorLabel.Visibility = System.Windows.Visibility.Hidden;
            }
        }

        void log_Data( StreamWriter stream )
        {
            counter ++;
            {
                stream.Write("<Placemark>\r\n"
                    +"<description><![CDATA[<i>Point #" + counter 
                    +"<br>Time: " + timeLabel.Text
                    +"<br>Time tag: "
                    +"<br>Latitude: " + latitude + " deg"
                    +"<br>Longitude: " + longitude + " deg"
                    +"<br>Altitude: " + altLabel.Text + " ft"
                    +"<br>Speed: " + speedLabel.Text + " mi/hr"
                    +"<br>Heading: " + heading + " deg"
                    +"<br>Fix indicator: 3-D"
                    +"<br>Used SVs: " + sat
                    +"</i>]]></description>\r\n"
                    +"<styleUrl>#dot</styleUrl>\r\n"
                    +"<Point><coordinates>" + longitude + "," + latitude + "," + System.Convert.ToString(altMeters)
                    +"</coordinates></Point>\r\n"
                    +"</Placemark>\r\n");
            }
        }

        StreamWriter make_NewLogFile()
        {
            String path = "D:\\" + fileName + ".kml" ;
            StreamWriter stream = new StreamWriter(path);
            {
                stream.Write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
                    +"<kml xmlns=\"http://earth.google.com/kml/2.2\">\r\n"
                    +"<Document>\r\n"
                    +"<name></name>\r\n"
                    +"<Style id=\"docIcon\">\r\n"
                    +"<ListStyle>\r\n"
                    +"<ItemIcon><href>C:\\Users\\Aditya\\AppData\\Roaming\\Trimble Navigation\\Trimble GPS Monitor\\0000FF.png</href></ItemIcon>\r\n"
                    +"<listItemType>checkHideChildren</listItemType>\r\n"
                    +"</ListStyle>\r\n"
                    +"</Style>\r\n"
                    +"<styleUrl>#docIcon</styleUrl>\r\n"
                    +"<Folder>\r\n"
                    +"<name>Points</name>\r\n"
                    +"<Style id=\"folderStyle\">\r\n"
                    +"<ListStyle>\r\n"
                    +"<ItemIcon><href>C:\\Users\\Aditya\\AppData\\Roaming\\Trimble Navigation\\Trimble GPS Monitor\\0000FF.png</href></ItemIcon>\r\n"
                    +"<listItemType>checkHideChildren</listItemType>\r\n"
                    +"</ListStyle>\r\n"
                    +"</Style>\r\n"
                    +"<styleUrl>#folderStyle</styleUrl>\r\n"
                    +"<Style id=\"dot\">\r\n"
                    +"<IconStyle>\r\n"  
                    +"<Icon><href>C:\\Users\\Aditya\\AppData\\Roaming\\Trimble Navigation\\Trimble GPS Monitor\\pointIcon.png</href></Icon>\r\n"
                    +"<color>FF0000FF</color>\r\n"
                    +"<colorMode>normal</colorMode>\r\n"
                    +"<scale>0.40</scale>\r\n"
                    +"<hotSpot x=\"0.5\" xunits=\"fraction\" y=\"0.5\" yunits=\"fraction\" />\r\n"
                    +"</IconStyle>\r\n"
                    +"<BalloonStyle>\r\n"
                    +"<textColor>FF800000</textColor>\r\n"
                    +"<bgColor>FFFFEFEF</bgColor>\r\n"
                    +"<text><![CDATA[<font size=+1><b><u>Details</u></b><br></font>]]>$[description]</text>\r\n"
                    +"</BalloonStyle>\r\n"
                    +"</Style>\r\n");
                return stream;
            }         
        }

        void close_LogFile( StreamWriter stream )
        {
            stream.Write("</Folder>\r\n"
                +"</Document>\r\n"
                +"</kml>\r\n");
            stream.Close();
        }
    }
}
